<?php

declare(strict_types=1);

/**
 * @Author:     Frank
 * @contact     frank_hhm@163.com
 * @Date:       2022-11-05 16:32:18
 * @Last Modified time: 2023-01-12 17:27:39
 */

namespace app\common\services\system;

use frank\base\BaseService;
use frank\services\JwtAuthService;
use frank\services\CacheService;
use frank\exception\CommonException;
use app\common\dao\system\AdminDao;
use app\common\services\system\MenusService;

/**
 * 管理员service
 * Class AdminService
 */
class AdminService extends BaseService
{

    /**
     * AdminServices constructor.
     * @param AdminDao $dao
     */
    public function __construct(AdminDao $dao)
    {
        $this->dao = $dao;
    }

    public function getDetail($filter)
    {
        $detail = $this->dao->detail($filter);
        if (!$detail) {
            throw new CommonException('数据不存在');
        }
        return $detail->toArray();
    }

    // 管理员登陆
    public function verifyLogin(string $account, string $password)
    {
        $adminInfo = $this->dao->accountByAdmin($account);
        if (!$adminInfo) {
            throw new CommonException('管理员不存在!');
        }
        if (!$adminInfo->status) {
            throw new CommonException('您已被禁止登录!');
        }
        if (!password_verify($password, $adminInfo->pwd)) {
            throw new CommonException('账号或密码错误，请重新输入',701);
        }
        $adminInfo->last_time = time();
        $adminInfo->last_ip = app('request')->ip();
        $adminInfo->login_count++;
        $adminInfo->save();

        return $adminInfo;
    }

    // 后台登陆获取菜单获取token
    public function login(string $account, string $password, string $type)
    {
        $adminInfo = $this->verifyLogin($account, $password);
        $tokenInfo = JwtAuthService::instance()->createToken($adminInfo->id, $type);
        $menusService = MenusService::instance();
        $menus = $menusService->getMenusList($adminInfo->roles, (int)$adminInfo['level']);
        $addonMenus = $menusService->getMenusList($adminInfo->roles, (int)$adminInfo['level'],2);
        $exp =  $tokenInfo['params']['exp'];
        if(!(int)$adminInfo['level']){
            $rolesApi = -1;
        }else{
            $rolesApi = $menusService->getApiList($adminInfo->roles, (int)$adminInfo['level']);
        }
        CacheService::instance()->set('system:admin:roles:'.$adminInfo->id,$rolesApi,$exp);
        return [
            'token' => $tokenInfo['token'],
            'expires_time' => $exp,
            'menus' => $menus,
            'addon_menus' => $addonMenus,
            'user_info' => $adminInfo->hidden(['pwd'])
        ];
    }


    /**
     * 创建管理员
     */
    public function create(array $data)
    {
        unset($data['conf_pwd']);
        if ($this->dao->count(['account' => $data['account'], 'delete_time' => 0])) {
            throw new CommonException('管理员账号已存在');
        }

        $data['pwd'] = $this->passwordHash($data['pwd']);
        $data['add_time'] = time();

        if (empty($data['roles'])) {
            throw new CommonException('请选择管理员角色');
        }
        return $this->transaction(function () use ($data) {
            if ($this->dao->save($data)) {
                return true;
            } else {
                throw new CommonException('添加失败');
            }
        });
    }

    /**
     * 修改管理员
     */
    public function updateSave($id, array $data)
    {
        if (!$adminInfo = $this->dao->get($id)) {
            throw new CommonException('管理员不存在,无法修改');
        }
        if ($adminInfo->delete_time) {
            throw new CommonException('管理员已经删除');
        }
        if (!$adminInfo->level && !empty($data['roles'])) {
            throw new CommonException('请选择管理员角色');
        }
        //修改密码
        if ($data['pwd']) {
            $adminInfo->pwd = $this->passwordHash($data['pwd']);
        }
        //修改账号
        if (isset($data['account']) && $data['account'] != $adminInfo->account && $this->dao->isAccountUsable($data['account'], $id)) {
            throw new CommonException('管理员账号已存在');
        }
        $adminInfo->real_name = $data['real_name'] ?? $adminInfo->real_name;
        $adminInfo->account = $data['account'] ?? $adminInfo->account;
        $adminInfo->roles = $data['roles'];
        $adminInfo->avatar = $data['avatar'];
        if ($adminInfo->save()) {
            return true;
        } else {
            return false;
        }
    }
}
